#!/usr/bin/env ruby


Thread.abort_on_exception = true   #otherwise, an exception in a thread fails silently

#This entire class is basically just a GUI builder.
#It depends on the Updateable and Getter classes for doing anything interesting.
class Weathenator
	require 'gtk2'
	require 'updateable.rb'
	require 'getter.rb'
	require 'graph.rb'
	
	#this builds the GUI. 
	#Basic structure - create all the controls first, then lay them all out in the window.
	#Laying out GUI's is messy!
   def initialize
   	#create a button to add a new updater
		add_button = Gtk::Button.new("Add updater")
		add_button.signal_connect("clicked") { add_updater }
		
		#create a combo box containing all the locations from the weather service
		@locations_combo_box = Gtk::ComboBox.new(is_text_only = true)
		LocationsGetter.new.get.sort.each{|loc| @locations_combo_box.append_text loc }
		@locations_combo_box.set_active(0)
		
		#make some check buttons to chose what kind of updater we want
		@chk_updaters = []
		@chk_updaters << @chk_temp = Gtk::CheckButton.new("Temp")
		@chk_updaters << @chk_rain = Gtk::CheckButton.new("Rainfall")
		@chk_temp.active = true #default to just temperature.
		
		
		
		#make a combo box to let the user choose how many minuites between updates
		@frequency_combo_box = Gtk::ComboBox.new(is_text_only = true)
		@frequency_combo_box.append_text "0.34"  #21 seconds... usefull for testing.
		(1..15).each{|n| @frequency_combo_box.append_text n.to_s }
		@frequency_combo_box.set_active(5)  #make the default 5 minuites

		
	##now we've finished making all the app's controls, lets lay them out	
	   #make the app window
	  @window = Gtk::Window.new
		@window.border_width = 10
		@window.default_width = 300
		@window.title = "Weathenator v2"
		@window.set_icon('images/sun_and_cloud.png')

      #now fill it with layout controls(verical boxes, horizontal boxes) and actual controls
      #laying out GUI's sucks.
      #No interesting behavior is located in here - its all layout. 
		  @vbox = Gtk::VBox.new(false, 0)  
			##BEGIN main column vertical stack

			menu_buttons = Gtk::HBox.new(false,15)
			   ##BEGIN menu horizontal flow
				menu_buttons.add @locations_combo_box
				type_box = Gtk::HBox.new(false,0)  #a box to contain the check buttons
					@chk_updaters.each{|u| type_box.add u }
				menu_buttons.add type_box 
				up_box = Gtk::HBox.new(false,0) #box for the frequency chooser.
					up_box.add Gtk::Label.new("Every")
					up_box.add @frequency_combo_box
					up_box.add Gtk::Label.new("min")
				menu_buttons.add up_box
				menu_buttons.add add_button
				##END menu horizontal flow
			@vbox.pack_start menu_buttons,expand=false    
			@vbox.pack_start(Gtk::HSeparator.new,true,true,10)

			##END mainbourneWeather column vertical stack
		@window.add @vbox
		@window.set_window_position Gtk::Window::POS_CENTER
		
		#enabling the following line avoids a lot of resizing issues.
		#@window.set_resizable(false)
		
		#in gtk you have to specifically program the ability to quit the program(hah!)
		@window.signal_connect('delete_event') { false }
		@window.signal_connect('destroy') { puts 'bye!'; Gtk.main_quit	}

		@window.show_all  #display everything to screen

		Gtk.main
	end
	
	#method called when the user clicks to add an updater. Creates result bars and graphs, etc.
	#extracted out of main for great clarity.
	def add_updater
		#grab the chosen location
		location = @locations_combo_box.active_text
		
		results_frame = Gtk::Frame.new(location)
		results_vstack = Gtk::VBox.new(false,0)
			##BEGIN add stuff to results row. This box contains all the widgets for an updater
		   row_hflow = Gtk::HBox.new(false,0)
		   
			#if we have more than one thing to monitor, we're gunna need more getters! So keep an array of them.
			#corresponding to this, we will keep an array of strings to describe the color of the plot line
			#for each of the getters. colours[0] is for getters[0], etc.
			getters = []; colours = [];
			
			#loop through the chosen updaters, and create their GTK bits.
			for checked in @chk_updaters.select{|c| c.active? } 
				if checked == @chk_temp
					image = Gtk::Image.new("images/thermometer-small.png")
					head_label = Gtk::Label.new "Temp at #{location} is "
					tail_label = Gtk::Label.new "C.  "
					getters << getter = TempGetter.new(location)
					colours << "red"
				elsif checked == @chk_rain
					image = Gtk::Image.new("images/rain-small.png")
					head_label = Gtk::Label.new "Rainfall at #{location} is "
					tail_label = Gtk::Label.new "mm.  "
					getters << getter = RainfallGetter.new(location)
					colours << "royalblue"
				end
				#add the chosen image and Updateable element to the 'row_hflow' 
				row_hflow.add image,{'expand' => false, 'fill'=> false}
				row_hflow.add head_label,{'expand' => false, 'fill'=> false}
			  
				#now we create & add the updateable element... setting its update frequency to 60 times the minuites specifed
				update_frequency = @frequency_combo_box.active_text.to_f * 60
				text_updater = UpdateableText.new(getter, update_frequency ).widget
			  	row_hflow.add text_updater,{'expand' => false, 'fill'=> false}
			  	row_hflow.add tail_label,{'expand' => false, 'fill'=> false}
		  end
		  
		  #create a button to destroy this row, align it to the right.
		  kill_box = Gtk::Alignment.new(1,0.5,0,0) 
			  delete_me = Gtk::Button.new("kill")
			 	delete_me.signal_connect("clicked") { results_frame.destroy }
			kill_box.add delete_me
		  row_hflow.pack_end kill_box
		  	
		  results_vstack.pack_start row_hflow,false,false,5
	   ##END stuffing of row
	    
	    #make a new graph from the getters.
	    graph = UpdateableGraph.new(getters[0],getters[1],update_frequency,
	    	        {:title => location, :colour1 => colours[0], :colour2 => colours[1]}).widget

	   	results_vstack.pack_start graph,false,false
	   
	   
	  results_frame.add results_vstack
	  @vbox.pack_start results_frame
		
		
		
		@window.show_all  #refreshes the window
	end
	
end

#kick the whole show off
Weathenator.new
